import os
import sys
import stat
import time
import logging
from ConfigParser import ConfigParser
from  urllib2 import urlopen
from  opslog.cli import settings
from opslog.cli.data import DataManager
from opslog.cli.plugins import BasePlugin

class Updater(BasePlugin):

    def start(self,client):
        super(Updater,self).start(client)
        if not self.client.args.script and self.__update_time():
            self.logger.info("Update available, please, run '%s update install'" % sys.argv[0])

    def setup_arguments(self,root_subparsers):
        update_parser = root_subparsers.add_parser("update",help="Update commands")
        update_subparsers = update_parser.add_subparsers()

        check_update_parser = update_subparsers.add_parser("check",help="Check for new versions")
        check_update_parser.set_defaults(run=self.check_updates)

        install_update_parser = update_subparsers.add_parser("install",help="Install any available update")
        install_update_parser.set_defaults(run=self.update)
    
    def __update_time(self):
        # Check for updates once a week
        last_update = DataManager.get("updater","last_update")
        if last_update: 
            if float(last_update) + 604800 < time.time():
                return True
        else:
            DataManager.set("updater","last_update","0")
        return False
    
    def check_updates(self):
        latest_version = self.get_latest_version()[0]
        my_version = self.get_my_version()[0]
        if latest_version > my_version:
            self.logger.info("New version available: %s (current: %s)" % (latest_version,my_version))
        else:
            self.logger.info("No updates found")
    

    def get_my_version(self):
        opslog_bin =  os.environ["OPSLOG_BIN"]
        if os.path.islink(opslog_bin):
            opslog_bin = os.readlink(opslog_bin)
        # Determine current version
        return (int(os.environ["OPSLOG_VERSION"]),opslog_bin)
         

    def get_latest_version(self):
        try:
            remote_data = urlopen(os.environ["OPSLOG_UPDATE_SERVER"])
            latest = ConfigParser()
            latest.readfp(remote_data)
    
            latest_version = latest.getint("latest","version")
            latest_location = latest.get("latest","location")
            return (latest_version,latest_location)
        except Exception as e:
            self.logger.warning("error: %s" % str(e) )
        return None

    def update(self):
        DataManager.set("updater","last_update",str(time.time()))
        latest_version,latest_location = self.get_latest_version()
        my_version,my_location = self.get_my_version()
        if latest_version > my_version:
            self.logger.info("Downloading update...")
            new_bin = urlopen(latest_location).read()
            #check perms
            old_mode = os.stat(my_location).st_mode
            self.logger.info("Installing update...")
            try:
                new_file = open(my_location,"wb")
                new_file.write(new_bin)
                new_file.close()
                os.chmod(my_location,old_mode|stat.S_IXUSR)
            except IOError as e:
                import errno
                if e.errno == errno.EACCES:
                    self.logger.warning("Can't update: no permissions to write file")
                else:
                    self.logger.warning("error: %s" % str(e))
            else:
                DataManager.set("updater","last_update",str(time.time()))
                self.logger.info("Version %s installed." % latest_version)
            
       
